// i.r(t), i.d(t, { USER_LABELS: () => E, default: () => X })
import Module from "./Module"
import SymbolList from "../SymbolList"
import LabelData from "../data/LabelData"
import CameraData from "../data/CameraData"
import FloorsViewData from "../data/FloorsViewData"
import ToolsData from "../data/ToolsData"
import MeshData from "../data/MeshData"
import SweepData from "../data/SweepData"
import RoomData from "../data/RoomData"
import SettingsData from "../data/SettingsData"
import Label3D from "../three/Label3D"
import Label3DFactory from "../three/Label3DFactory"
import * as THREE from "three"
import Color from "../three/Color"
const v = {
  ColorDefault: 16777215,
  ColorHovered: Color.MP_BRAND.getHex(),
  ColorInvalid: 16750933
}
class LabelTextMesh extends Label3D {
  use(e) {
    ;(this.userData.sid = e.data.sid), (this.collider.data = e.data), (this.collider.name = e.data.text), (this.collider.labelMesh = e)
  }
}

class LabelPartMaker {
  makeLabel: () => LabelTextMesh
  textStyle: any
  layer: any
  constructor(e) {
    ;(this.makeLabel = () => {
      const e = new LabelTextMesh(Object.assign({}, this.textStyle))
      return (e.scaleType = FontScaleType.WORLD), e.setRenderOrder(renderOrderEnum.labels), e.setRenderLayer(this.layer), (e.opacity = 0), e
    }),
      (this.textStyle = Label3DFactory.makeConfig({
        color: "white",
        background: !e,
        backgroundAsCollider: !0,
        backgroundColliderType: LabelTextBackgroundMesh,
        backgroundColor: "#222",
        backgroundOpacity: 1,
        outline: e,
        outlineWidth: 8,
        backgroundBorderHeight: 26,
        backgroundBorderWidth: 20,
        wordWrapWidth: void 0,
        disableDepth: !0
      }))
  }
  setRenderLayer(e) {
    this.layer = e
  }
}
import ObservableMap, { createMap } from "../observer/observable.map"
import AnimatedNumber from "../object/AnimatedNumber"
const E = {
  LABEL_SIZE: 0,
  FADE_DURATION: 200,
  ANCHOR_2D_COLLAPSE_RADIUS: 20,
  ANCHOR_MAX_RADIUS: 0.09,
  ANCHOR_MIN_RADIUS: 0.04,
  ANCHOR_OPACITY: 1,
  LINE_OPACITY: 0.4,
  ANCHOR_OPACITY_COLLAPSE: 0,
  LABEL_OPACITY_COLLAPSE: 0,
  SCREEN_FILTER_WIDTH_FACTOR: 0,
  SHOW_ANCHOR: 1 === funcUtil.getUrlParams("anchor", 0),
  DEBUG: -1 !== funcUtil.getUrlParams("debug", "").indexOf("labels")
}
import funcUtil from "../utils/func.util"

class LabelMesh extends THREE.Object3D {
  text: any
  maxOpacity: number
  labelAnim: AnimatedNumber
  filtered: boolean
  hidden: boolean
  selectState: { active: boolean; on: () => void; off: () => void }
  validState: { active: boolean; on: () => void; off: () => void }
  hoverState: any
  data: any
  constructor(e) {
    super(),
      (this.text = e),
      (this.maxOpacity = 1),
      (this.labelAnim = new AnimatedNumber(0)),
      (this.filtered = !1),
      (this.hidden = !1),
      (this.selectState = { active: !1, on: () => {}, off: () => {} }),
      (this.validState = {
        active: !0,
        on: () => {
          const e = this.hoverState.active ? v.ColorHovered : v.ColorDefault
          this.text.setColorHex(e)
        },
        off: () => {
          this.text.setColorHex(v.ColorInvalid)
        }
      }),
      (this.hoverState = {
        active: !1,
        on: () => {
          this.validState.active && this.text.setColorHex(v.ColorHovered)
        },
        off: () => {
          this.validState.active && this.text.setColorHex(v.ColorDefault)
        }
      }),
      this.add(e)
  }
  use(e) {
    ;(this.data = e), (this.userData.sid = e.sid), (this.userData.data = e), this.text.use(this), this.labelUpdate(e.position, new THREE.Quaternion(), "")
  }
  getId() {
    return this.data.sid
  }
  labelVisible() {
    return !this.filtered && !this.hidden
  }
  updatePose(e, t) {
    return this.labelUpdate(e, t, this.data.text), this
  }
  setMaxOpacity(e) {
    ;(this.maxOpacity = e), this.toggleLabel(this.labelVisible())
  }
  async free() {
    this.labelAnim.value > 0 && (this.toggleLabel(!1), await funcUtil.waitRun(E.FADE_DURATION))
  }
  tickAnimations(e) {
    return this.animateLabelOpacity(0.5 * e), this
  }
  toggleLabel(e) {
    ;(this.hidden = !e), this.updateOpacity()
  }
  isHidden() {
    return this.hidden
  }
  toggleFiltered(e) {
    e !== this.filtered && ((this.filtered = e), this.updateOpacity())
  }
  updateOpacity() {
    const e = this.labelVisible() ? this.maxOpacity : 0
    this.labelAnim.endValue !== e && this.labelAnim.modifyAnimation(this.labelAnim.value, e, E.FADE_DURATION)
  }
  animateLabelOpacity(e) {
    const t = this.labelAnim.tick(e)
    Math.min(t, this.maxOpacity) !== this.text.opacity && (this.text.opacity = t)
  }
  labelUpdate(e, t, i) {
    this.text.position.copy(e), this.text.quaternion.copy(t), (this.text.text = i)
  }
  billboard(e, t, i, n, s, r, o) {
    this.text.scaleBillboard(e, t, i, n, s, r, o)
  }
}
import Logger from "../utils/Logger"

const _ = new Logger("label-spawner")
class LabelSpawner {
  map: any
  maker: any
  container: THREE.Object3D
  pool: any[]
  bindings: any[]
  meshesMap: ObservableMap<any>
  constructor(e, t) {
    ;(this.map = e),
      (this.maker = t),
      (this.container = new THREE.Object3D()),
      (this.pool = []),
      (this.bindings = []),
      (this.meshesMap = createMap()),
      (this.container.name = "RoomLabels")
    const i = e.keys
    for (const t of i) {
      const i = e.get(t)
      this.add(i, t)
    }
    this.bindings.push(
      e.onElementChanged({
        onAdded: (e, t) => {
          this.add(e, t), _.debug("LabelMesh: added:", t)
        },
        onRemoved: (e, t) => {
          _.debug("LabelMesh: removing:", t)
          const i = this.meshesMap.get(t)
          i && this.free(i)
        }
      })
    )
  }
  subscribe(e) {
    return this.meshesMap.onElementChanged(e)
  }
  get(e) {
    return this.meshesMap.get(e)
  }
  free(e) {
    const t = e.getId(),
      i = this.meshesMap.get(t)
    return i.free().then(() => {
      this.meshesMap.delete(t), this.container.remove(i), this.pool.push(i), _.debug("LabelMesh: removed:", i)
    })
  }
  add(e, t) {
    const i = this.get(t)
    if (i) return i
    const n = this.pool.shift()
    if (void 0 !== n) return n.use(e), this.container.add(n), this.meshesMap.set(t, n), n
    {
      const i = new LabelMesh(this.maker.makeLabel())
      return i.use(e), this.container.add(i), this.meshesMap.set(t, i), i
    }
  }
  dispose() {
    for (const e of this.meshesMap.values) this.free(e)
    this.bindings.forEach(e => e.cancel())
  }
}
import M from "../math/19674"

class LabelRenderer {
  meshes: any
  cameraData: any
  screenFilter: any
  dirty: boolean
  bindings: any[]
  pendingMesh: any
  setDirty: () => void
  constructor(e, t, i, n) {
    ;(this.meshes = e),
      (this.cameraData = i),
      (this.screenFilter = n),
      (this.dirty = !0),
      (this.bindings = []),
      (this.pendingMesh = null),
      (this.setDirty = () => {
        this.dirty = !0
      }),
      this.bindings.push(i.onChanged(this.setDirty), t.onChanged(this.setDirty))
    for (const e of this.meshes.values) e.text.onGeomUpdate(this.setDirty)
    this.meshes.onElementChanged({
      onAdded: e => e.text.onGeomUpdate(this.setDirty)
    })
  }
  dispose() {
    this.bindings.forEach(e => e.cancel()), (this.bindings.length = 0)
  }
  setPendingMeshId(e) {
    if (
      (!this.pendingMesh || this.pendingMesh.getId() !== e) &&
      (this.pendingMesh && (this.pendingMesh.data.removeOnChanged(this.setDirty), (this.pendingMesh = null)), e)
    ) {
      const t = this.meshes.get(e)
      t.data.onChanged(this.setDirty), (this.pendingMesh = t)
    }
  }
  beforeRender() {
    if (!this.dirty) return
    this.dirty = !1
    const { position: e, rotation: t, projection: i } = this.cameraData.pose,
      { height: n } = this.cameraData,
      s = this.cameraData.zoom(),
      r = this.cameraData.aspect(),
      o = M.dS(64 - E.LABEL_SIZE, 0, 64, 0.02, 0.1)
    for (const a of this.meshes.values) a.isHidden() || (a.updatePose(a.data.position, t), a.billboard(e, t, i, s, n, r, o))
    this.screenFilter.update()
    for (const e of this.meshes.values) e.isHidden() || e.toggleFiltered(!this.screenFilter.visible(e.data.sid))
  }
  render(e) {
    for (const t of this.meshes) t.tickAnimations(e)
  }
  deactivate() {}
  init() {}
  activate() {}
}

import RBush from "rbush"
import O from "../math/27687"

class Label2DFiltering {
  meshes: any
  cameraData: any
  enabled: any
  tree: RBush<unknown>
  visibleMap: {}
  _screenPosition: THREE.Vector2
  _ndcPosition: THREE.Vector3
  _cornerWorldPosition: THREE.Vector3
  _cornerScreenPosition: THREE.Vector2
  _selectedId: any
  update: () => void
  constructor(e, t, i) {
    ;(this.meshes = e),
      (this.cameraData = t),
      (this.enabled = i),
      (this.tree = new RBush()),
      (this.visibleMap = {}),
      (this._screenPosition = new THREE.Vector2()),
      (this._ndcPosition = new THREE.Vector3()),
      (this._cornerWorldPosition = new THREE.Vector3()),
      (this._cornerScreenPosition = new THREE.Vector2()),
      (this._selectedId = null),
      (this.update = () => {
        this.enabled() ? ((this.visibleMap = {}), this.updatePositions()) : Object.keys(this.visibleMap).length && (this.visibleMap = {})
      })
  }
  visible(e) {
    if (!(e in this.visibleMap)) return !1
    return e in this.visibleMap
  }
  setSelectedMeshId(e) {
    this._selectedId = e
  }
  updatePositions() {
    this.tree.clear(),
      this.meshes()
        .filter(e => !e.isHidden())
        .map(e => {
          O.q9(this.cameraData, e.text.position, this._screenPosition, this._ndcPosition)
          const { width: t, height: i } = e.text.textGeometry.layout
          this._cornerWorldPosition.set(0.5 * t, -0.5 * i, 0),
            e.text.updateMatrixWorld(),
            this._cornerWorldPosition.applyMatrix4(e.text.matrixWorld),
            O.q9(this.cameraData, this._cornerWorldPosition, this._cornerScreenPosition)
          const n = e.getId() !== this._selectedId ? this._ndcPosition.z : -999
          return this.describeBbox(e.text, this._screenPosition, this._cornerScreenPosition, n)
        })
        .sort((e, t) => e.depth - t.depth)
        .forEach(e => {
          this.tree.collides(e) || (this.tree.insert(e), (this.visibleMap[e.id] = e))
        })
  }
  describeBbox(e, t, i, n) {
    i.sub(t)
    const s = i.x,
      r = i.y
    return {
      id: e.userData.sid,
      depth: n,
      minX: t.x - s,
      minY: t.y - r,
      maxX: t.x + s,
      maxY: t.y + r
    }
  }
}
import ApplicationData from "../data/ApplicationData"
import labelTypeEnum from "../enum/labelType.enum"
import ViewmodeData from "../data/ViewmodeData"
class LabelVisibilityRules {
  meshes: any
  initialized: boolean
  searchResultsData: any
  pendingMeshId: any
  dirty: boolean
  bindings: any[]
  focusedGroup: any
  updateFocusedGroup: (e: any) => void
  featureEnabled: () => any
  appData: any
  settingsData: any
  visibleByTool: () => boolean
  toolsData: any
  visibleByViewmode: () => any
  viewmodeData: any
  hiddenByTransition: () => any
  floorsViewData: any
  visibleByFloor: (e: any) => any
  setDirty: () => void
  dirtyCb: any
  constructor(e) {
    ;(this.meshes = e),
      (this.initialized = !1),
      (this.searchResultsData = null),
      (this.pendingMeshId = null),
      (this.dirty = !0),
      (this.bindings = []),
      (this.focusedGroup = null),
      (this.updateFocusedGroup = e => {
        this.focusedGroup = e.results.filter(e => e.type === labelTypeEnum.LABEL).map(e => e.id)
      }),
      (this.featureEnabled = () => {
        if (!this.initialized) return !1
        const e = this.appData.phase === phaseMin.PLAYING,
          t = this.settingsData.tryGetProperty(keyConst.rule.features.roomnav, !1),
          i = this.settingsData.tryGetProperty(keyConst.rule.features.labels, !1),
          n = this.appData.application === appTypeMin.WORKSHOP,
          s = this.settingsData.tryGetProperty(optionsKeyEnum.Labels, !1) || n
        return e && i && s && (t || n)
      }),
      (this.visibleByTool = () =>
        !!this.initialized &&
        (null === this.toolsData.activeToolName ||
          this.toolsData.activeToolName === ToolsList.LABELS ||
          this.toolsData.activeToolName === ToolsList.PHOTOS ||
          this.toolsData.activeToolName === ToolsList.SEARCH)),
      (this.visibleByViewmode = () => {
        const e = this.settingsData.tryGetProperty(keyConst.rule.features.roomnav, !1),
          t = this.settingsData.tryGetProperty(optionsKeyEnum.LabelsDollhouse, !1) || (e && this.toolsData.activeToolName === ToolsList.LABELS),
          i = this.viewmodeData.isDollhouse() && t && e
        return (
          (this.viewmodeData.isFloorplan() &&
            ((this.appData.application === appTypeMin.WORKSHOP && this.visibleByTool()) ||
              (e && this.settingsData.tryGetProperty(optionsKeyEnum.Labels, !1)))) ||
          i
        )
      }),
      (this.hiddenByTransition = () => this.viewmodeData.transitionActive() || this.floorsViewData.transitionActive),
      (this.visibleByFloor = e => {
        const t = this.settingsData.tryGetProperty(keyConst.rule.features.roomnav, !1),
          i = this.toolsData.activeToolName === ToolsList.LABELS
        if (t && !i) {
          const { roomSelectModeActive: e, floorSelectModeActive: t } = this.floorsViewData
          if (!e) return !1
          if (t) return !1
        }
        return this.viewmodeData.isFloorplan()
          ? this.floorsViewData.currentFloor
            ? this.floorsViewData.isCurrentOrAllFloors(e)
            : this.floorsViewData.topFloorId === e
          : this.floorsViewData.isCurrentOrAllFloors(e)
      }),
      (this.setDirty = () => {
        ;(this.dirty = !0), this.dirtyCb && this.dirtyCb()
      })
  }
  async init(e) {
    ;[this.viewmodeData, this.floorsViewData, this.settingsData, this.toolsData, this.appData] = await Promise.all([
      e.waitForData(ViewmodeData),
      e.waitForData(FloorsViewData),
      e.waitForData(SettingsData),
      e.waitForData(ToolsData),
      e.waitForData(ApplicationData)
    ])
    const t = await e.waitForData(LabelData)
    ;[this.viewmodeData, this.floorsViewData, this.settingsData, this.toolsData, this.appData, t].forEach(e => this.bindings.push(e.onChanged(this.setDirty)))
    this.meshes.onChanged(this.setDirty)
    this.setDirty()
    this.initialized = !0
  }
  dispose() {
    this.bindings.forEach(e => e.cancel()), (this.bindings.length = 0)
  }
  visibleByFocusedGroup(e) {
    var t
    return !this.searchResultsData || !this.searchResultsData.getQuery() || !!(null === (t = this.focusedGroup) || void 0 === t ? void 0 : t.includes(e))
  }
  onUpdate() {
    if (!this.initialized || !this.dirty) return
    this.dirty = !1
    const e = this.featureEnabled(),
      t = !this.hiddenByTransition(),
      i = this.visibleByTool(),
      n = e && t && i && this.visibleByViewmode()
    this.settingsData.setProperty(keyConst.rule.features.labels_visble, n)
    for (const e of this.meshes.values) {
      const t =
        n &&
        (this.visibleByFloor(e.data.floorId) || e.data.sid === this.pendingMeshId) &&
        e.data.visible &&
        (!this.searchResultsData || this.visibleByFocusedGroup(e.data.sid))
      e.toggleLabel(t)
    }
  }
  setPendingMeshId(e) {
    ;(this.pendingMeshId = e), (this.dirty = !0)
  }
  setDirtyCallback(e) {
    this.dirtyCb = e
  }
}
import transitionTypeEnum from "../enum/transitionType.enum"
import Comparator from "../utils/Comparator"
import { createSubscription } from "../utils/Subscription"
import AggregateSubscription from "../utils/AggregateSubscription"
import { SetMouseCursorCommand } from "../command/cursor.command"
import browserUtil from "../utils/browser.util"
class LabelRendererInput {
  labelRenderer: any
  issueCommand: any
  input: any
  floorsViewData: any
  toolsData: any
  roomNavigationPose: any
  inputBindings: any[]
  appStateBindings: any[]
  raycasterRegistrationBindings: any[]
  active: boolean
  enabled: boolean
  refresh: () => void
  refreshColliders: () => void
  clearColliders: () => void
  constructor(e, t, i, n, s, r) {
    ;(this.labelRenderer = e),
      (this.issueCommand = t),
      (this.input = i),
      (this.floorsViewData = n),
      (this.toolsData = s),
      (this.roomNavigationPose = r),
      (this.inputBindings = []),
      (this.appStateBindings = []),
      (this.raycasterRegistrationBindings = []),
      (this.active = !0),
      (this.enabled = !0),
      (this.refresh = () => {
        this.shouldBeInteractive !== this.active &&
          (this.inputBindings.forEach(e => (this.shouldBeInteractive ? e.renew() : e.cancel())),
          this.raycasterRegistrationBindings.forEach(e => (this.shouldBeInteractive ? e.renew() : e.cancel())),
          (this.active = this.shouldBeInteractive))
      }),
      (this.refreshColliders = () => {
        for (const e of this.labelRenderer.labelMeshIterator())
          this.shouldBeInteractive ? this.input.registerMesh(e.text.collider, !1) : this.input.unregisterMesh(e.text.collider)
      }),
      (this.clearColliders = () => {
        for (const e of this.labelRenderer.labelMeshIterator()) this.input.unregisterMesh(e.text.collider)
      }),
      this.inputBindings.push(...this.setupInputBindings()),
      this.raycasterRegistrationBindings.push(...this.setupRaycasterBindings())
    const o = this.toolsData.onToolChanged(this.refresh),
      a = this.floorsViewData.makeFloorChangeSubscription(this.refresh),
      l = this.floorsViewData.onRoomSelectModeChange(this.refresh)
    this.appStateBindings.push(o, a, l), this.refresh()
  }
  toggleInput(e) {
    this.enabled !== e && ((this.enabled = e), this.appStateBindings.forEach(t => (e ? t.renew() : t.cancel())), this.refresh())
  }
  get shouldBeInteractive() {
    return this.enabled && null === this.toolsData.activeToolName && this.floorsViewData.roomSelectModeActive
  }
  setupRaycasterBindings() {
    return [
      createSubscription(
        () => this.refreshColliders(),
        () => this.clearColliders(),
        !0,
        "toggleLabelMeshInput"
      ),
      this.labelRenderer.subscribe({
        onAdded: e => this.input.registerMesh(e.text.collider, !1),
        onRemoved: e => this.input.unregisterMesh(e.text.collider)
      })
    ]
  }
  setupInputBindings() {
    const e = Comparator.is(e => e instanceof LabelTextBackgroundMesh && e.labelVisible()),
      t = this.input.registerMeshHandler(ClickEvent, e, (e, t) => {
        const i = this.labelRenderer.getLabelMesh(t.getId())
        if (i) {
          const e = i.data.roomId,
            t = this.roomNavigationPose.getPoseForRoom(e, i.data.position)
          t && this.issueCommand(new ChangeViewmodeCommand(modeEnum.INSIDE, transitionTypeEnum.Interpolate, t))
        }
      })
    if (browserUtil.canTouch()) return [t]
    let i = null
    return [
      new AggregateSubscription(
        this.input.registerMeshHandler(HoverEvent, e, (e, t) => {
          const n = this.labelRenderer.getLabelMesh(t.getId())
          n && ((n.hoverState.active = !0), n.hoverState.on(), (i = n), this.issueCommand(new SetMouseCursorCommand(cursorEnum.FINGER)))
        }),
        this.input.registerMeshHandler(UnhoverEvent, Comparator.isType(LabelTextBackgroundMesh), (e, t) => {
          i && this.issueCommand(new SetMouseCursorCommand(cursorEnum.DEFAULT))
          const n = this.labelRenderer.getLabelMesh(t.getId())
          n && ((n.hoverState.active = !1), n.hoverState.off()), (i = null)
        }),
        createSubscription(
          () => {},
          () => {
            i && ((i.hoverState.active = !1), i.hoverState.off(), this.issueCommand(new SetMouseCursorCommand(cursorEnum.DEFAULT)), (i = null))
          },
          !0,
          "labelHoverClear"
        )
      ),
      t
    ]
  }
}
import Vectors from "../three/Vectors"
const $ = new Logger("room-with-a-view")
class RoomNavigationPose {
  sweepData: any
  roomData: any
  meshData: any
  constructor(e, t, i) {
    ;(this.sweepData = e), (this.roomData = t), (this.meshData = i)
  }
  getPoseForRoom(e, t) {
    const i = this.bestViewForRoom(e, t)
    if (i) {
      return {
        rotation: i.rotation,
        sweepID: i.sweepID,
        viewmode: viewmodeEnum.Panorama
      }
    }
    return null
  }
  bestViewForRoom(e, t) {
    const i = this.sweepData.filter(t => t.roomId === e && t.enabled)
    if (0 === i.length)
      return (
        $.debug("no sweeps in selected room", {
          roomId: e,
          scansInRoom: i
        }),
        null
      )
    let n = 1
    const s = this.roomData.get(e),
      r = this.meshData.meshGroups.rooms.get(s.meshGroup, s.meshSubgroup),
      o = (null == r ? void 0 : r.boundingBox.getSize(new THREE.Vector3()).length()) || 1 / 0
    t && o > 10 && (n = 0.2)
    const a = i.sort((i, s) => {
        let r = 0,
          o = 0
        t && ((r = i.position.distanceTo(t)), (o = s.position.distanceTo(t)))
        const a = i.neighbours.map(e => this.sweepData.getSweep(e)).filter(t => t.roomId === e).length,
          l = s.neighbours.map(e => this.sweepData.getSweep(e)).filter(t => t.roomId === e).length
        return 1 * n * (l - a) - 3 * (o - r)
      }),
      l = a[0]
    if (!l)
      return (
        $.debug("no start sweep", {
          roomId: e,
          scansInRoom: i,
          connectedness: a
        }),
        null
      )
    const c = l.neighbours
        .map(e => this.sweepData.getSweep(e))
        .sort((t, i) => {
          let n = l.position.distanceTo(t.position),
            s = l.position.distanceTo(i.position)
          return t.roomId === e && (n *= 1e3), i.roomId === e && (s *= 1e3), s - n
        })
        .map(e => ({
          sweep: e,
          dist: l.position.distanceTo(e.position),
          rm: e.roomId
        })),
      h = c[0]
    $.warn({
      roomId: e,
      roomSize: o,
      scoring: a,
      byDistance: c,
      scansInRoom: i
    })
    const d = new THREE.Quaternion()
    if (1 === i.length && void 0 !== h) {
      const e = new THREE.Matrix4().setPosition(l.position)
      e.lookAt(h.sweep.position, l.position, Vectors.UP), d.setFromRotationMatrix(e)
    } else {
      const e = new THREE.Matrix4().setPosition(l.position)
      e.lookAt(l.position, h.sweep.position, Vectors.UP), d.setFromRotationMatrix(e)
    }
    return { sweepID: l.id, rotation: d }
  }
}

import { RTLDisabledRoomnavMessage } from "../message/rtl.message"
import { ChangeViewmodeCommand } from "../command/viewmode.command"
import optionsKeyEnum from "../enum/optionsKey.enum"
import { phaseMin } from "../enum/phase.enum"
import { appTypeMin } from "../enum/appType.enum"
import cursorEnum from "../enum/cursor.enum"
import keyConst from "../constant/key.const"
import { ToolsList } from "../enum/tool.enum"
import modeEnum from "../enum/mode.enum"
import LabelTextBackgroundMesh from "../mesh/LabelTextBackgroundMesh"
import renderOrderEnum from "../enum/renderOrder.enum"
import { ClickEvent, HoverEvent, UnhoverEvent } from "../event/GestureEvent"
import { FontScaleType } from "../enum/font.enum"
import viewmodeEnum from "../enum/viewmode.enum"
export default class LabelRendererModule extends Module {
  labelMeshIterator: () => any
  spawner: any
  checkForRTL: (i: any, n: any) => void
  visibilityRules: LabelVisibilityRules
  labelFilter: Label2DFiltering
  labelRenderer: LabelRenderer
  labelNavInput: LabelRendererInput
  constructor() {
    super(...arguments),
      (this.name = "user-labels"),
      (this.labelMeshIterator = () => this.spawner.meshesMap.values),
      (this.checkForRTL = (() => {
        const e = /[\u0591-\u07FF]/
        let t
        return (i, n) => {
          if (!n.tryGetProperty(keyConst.rule.features.roomnav, !1)) return
          const s = i => {
            n.tryGetProperty(keyConst.rule.features.roomnav, !1) &&
              e.test(i.text) &&
              (this.broadcast(new RTLDisabledRoomnavMessage()), n.setProperty(keyConst.rule.features.roomnav, !1), t && t.cancel())
          }
          i
            .getCollection()
            .entries()
            .forEach(e => s(e[1])),
            n.tryGetProperty(keyConst.rule.features.roomnav, !1) &&
              ((t = i.getCollection().onElementChanged({ onAdded: s, onUpdated: s })), this.bindings.push(t))
        }
      })())
  }
  broadcast: any
  async init(e, t) {
    const [i, n, p, m, g, f, v, y, b, S] = await Promise.all([
        t.market.waitForData(LabelData),
        t.market.waitForData(CameraData),
        t.market.waitForData(FloorsViewData),
        t.market.waitForData(ToolsData),
        t.market.waitForData(SweepData),
        t.market.waitForData(RoomData),
        t.market.waitForData(MeshData),
        t.getModuleBySymbol(SymbolList.WEBGL_RENDERER),
        t.getModuleBySymbol(SymbolList.INPUT),
        t.market.waitForData(SettingsData)
      ]),
      E = y.getScene()
    ;(this.broadcast = t.broadcast), this.checkForRTL(i, S)
    const T = new LabelPartMaker(S.tryGetProperty(keyConst.rule.features.roomnav, !1))
    T.setRenderLayer(t.claimRenderLayer("labels")),
      (this.spawner = new LabelSpawner(i.getCollection(), T)),
      E.add(this.spawner.container),
      (this.visibilityRules = new LabelVisibilityRules(this.spawner.meshesMap)),
      this.visibilityRules.init(t.market)
    ;(this.labelFilter = new Label2DFiltering(this.labelMeshIterator, n, () => this.visibilityRules.featureEnabled() && this.visibilityRules.visibleByTool())),
      (this.labelRenderer = new LabelRenderer(this.spawner.meshesMap, i.getCollection(), n, this.labelFilter)),
      t.addComponent(this, this.labelRenderer),
      this.visibilityRules.setDirtyCallback(this.labelRenderer.setDirty)
    const w = new RoomNavigationPose(g, f, v)
    ;(this.labelNavInput = new LabelRendererInput(this, t.commandBinder.issueCommand, b, p, m, w)), this.toggleInput(!0)
  }
  dispose(e) {
    super.dispose(e), this.visibilityRules.dispose()
  }
  getLabelMesh(e) {
    return (e && this.spawner.get(e)) || null
  }
  addLabelMesh(e, t) {
    return this.spawner.add(e, t)
  }
  freeLabelMesh(e) {
    e && this.spawner.free(e)
  }
  setPendingMeshId(e) {
    this.visibilityRules.setPendingMeshId(e), this.labelRenderer.setPendingMeshId(e)
  }
  setSelectedMeshId(e) {
    this.labelFilter.setSelectedMeshId(e)
  }
  toggleInput(e) {
    this.labelNavInput.toggleInput(e)
  }
  subscribe(e) {
    return this.spawner.subscribe(e)
  }
  onUpdate() {
    this.visibilityRules && this.visibilityRules.onUpdate()
  }
}
